/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.scheduler.job;

import java.util.Calendar;
import java.util.Collection;

import jp.aist.gtrc.plus.scheduler.status.JobStatus;
import jp.aist.gtrc.plus.scheduler.util.TimeUtil;

import org.apache.log4j.Logger;


public class StarvedJobHelper {

	private static final int DEFAULT_STARVE_TIME = 24 * 3600; // [sec]
	private int starveTime = DEFAULT_STARVE_TIME;
	private static final int NORMAL_MAX_PRIORITY = 1024;

	protected static final Logger logger = Logger.getLogger(StarvedJobHelper.class);

	public StarvedJobHelper(int starveTime) {

		if (starveTime < 0) {
			/*
			 * We allow very short starveTime such as 60sec or 0sec.
			 * starveTime=0 means FIFO scheduler actually because
			 * first submitted job is longest starved (waiting to run)
			 * so it has highest job priority.
			 */
			starveTime = 0;
		}

		this.starveTime = starveTime;

	}

	void helpStarved(Collection<JobStatus> jobs) {

		int now = TimeUtil.calToSec(Calendar.getInstance());

		for (JobStatus job : jobs) {
			int submitTime = TimeUtil.calToSec(job.getSubmitTime());
			if ((submitTime + starveTime) < now) {
				/*
				 * Set higher priority to longer starved jobs, ignore original priority.
				 * New priority is 'job is starved period in sec' + 1024.
				 * 1024 is Torque's normal highest priority.
				 * Original Torque doesn't add 1024, but it can't guarantee that
				 * 'starved job priority is always higher than not starved'.
				 * see update_starvation() @ src/scheduler.cc/samples/fifo/fifo.c
				 */
				/*
				 * job.setPriority() only changes local object value, not changes
				 * real priority value managed by pbs_server.
				 * New priority value is valid only for one scheduling cycle.
				 */
				int newPrio = (now - submitTime - starveTime) + NORMAL_MAX_PRIORITY;
				logger.debug("Change priority of " + job.getJobID().toString() + " from "
						+ job.getPriority() + " to " + newPrio + " temporary");
				job.setPriority(newPrio);
			}
		}

	}

}
